import os
import time

try:
    import wx
except Exception:
    pass
from core.adb_interface import AdbInterface
from core.thread_extra import LogicThread
from core.status_logger import LogStatus as CLogger
from core.yaml_extra import YamlLoaderWithLog


class CustomScriptThread(LogicThread):
    """脚本执行线程"""

    def __init__(self, adb: AdbInterface, actions: [list, tuple] = None, times: int = None, file: str = None, parent=None):
        LogicThread.__init__(self, parent=parent)
        if not isinstance(parent, CustomScriptThread):
            parent = None
        self.adb = adb if adb is not None else (
            parent.adb if parent is not None else None
        )
        self.use_file = actions is None and file is not None
        self.use_parent = actions is None and file is None and parent is not None
        self.file = file
        self.dir = os.path.dirname(file) if file is not None else(
            parent.dir if parent is not None else ""
        )
        if self.use_file:
            if not os.path.exists(self.file):
                self.log_msg("配置文件({})不存在.\n".format(self.file), CLogger.MsgType.ERROR)
                return
            with YamlLoaderWithLog(self.file, logger=self.logger) as f:
                conf = f.load_dict()
                if "name" in conf:
                    self.log_msg("脚本：" + str(conf["name"]) + "\n", CLogger.MsgType.INFO)
                if "loop" in conf and times is None:
                    self.loop_infinite = bool(conf["loop"])
                    self.loop_times = -1 if self.loop_infinite else 1
                if "times" in conf and times is None:
                    self.loop_times = conf["times"]
                    self.loop_infinite = self.loop_times < 0
                if "tip" in conf:
                    self.log_msg("提示：" + str(conf["tip"]) + "\n", CLogger.MsgType.INFO)
                if "actions" in conf:
                    self.actions = conf["actions"]
        elif self.use_parent:
            self.actions = parent.actions
            self.loop_infinite = parent.loop_infinite if times is None else self.loop_infinite
            self.loop_times = parent.loop_times if times is None else self.loop_times
        else:
            self.actions = actions
            self.loop_infinite = times < 0 if times is not None else False
            self.loop_times = times if times is not None else 1
        pass

    def sleep(self, seconds):
        sleep_start = time.time()
        sleep_stop = sleep_start + seconds
        while time.time() < sleep_stop:
            self._flag_continue.wait()
            if not self._flag_run.is_set():
                return False
            time.sleep(max(0, min(sleep_stop - time.time(), 1)))
        return True

    def execute(self):
        if self.adb is None:
            self.log_msg("没有Adb对象.\n", CLogger.MsgType.ERROR)
            return
        succ, dev = self.adb.list_devices()
        if not succ or len(dev) is 0:
            self.log_msg("没有检测到设备.\n", CLogger.MsgType.ERROR)
            return
        if self.actions is None or len(self.actions) is 0:
            self.log_msg("操作指令为空！\n")
            return
        tm_start = tm_flag = time.time()
        loop_count = 0
        try:
            self._flag_stopped.clear()
            self._flag_continue.set()
            self._flag_run.set()
            self.reset_progress()
            action_count = len(self.actions)
            while self._flag_run.is_set():
                for i in range(action_count):
                    try:
                        action = self.actions[i]
                        keys = action.keys()
                        act = action["act"] if "act" in keys else "nop"
                        act_time = float(action["time"]) if "time" in keys else 0.0
                        if act == "click":
                            if "x" in keys and "y" in keys:
                                x = int(action["x"])
                                y = int(action["y"])
                                self.log_msg("点击 ({},{})\n".format(x, y))
                                self.adb.click(x, y)
                            else:
                                self.log_msg("点击{{x,y}} 参数错误({})\n".format(action), CLogger.MsgType.ERROR)
                        elif act == "slide":
                            if "x1" in keys and "y1" in keys and "x2" in keys and "y2" in keys:
                                x1 = int(action["x1"])
                                y1 = int(action["y1"])
                                x2 = int(action["x2"])
                                y2 = int(action["y2"])
                                self.log_msg("滑动 ({},{})=>({},{}) {}s\n".format(x1, y1, x2, y2, act_time))
                                self.adb.slide(x1, y1, x2, y2, int(act_time * 1000))
                            else:
                                self.log_msg("滑动{{x1,y1,x2,y2,time}} 参数错误({})\n".format(action), CLogger.MsgType.ERROR)
                        elif act == "press":
                            if "x" in keys and "y" in keys:
                                x = int(action["x"])
                                y = int(action["y"])
                                self.log_msg("按住 ({},{}) {}s\n".format(x, y, act_time))
                                self.adb.press(x, y, int(act_time * 1000))
                            else:
                                self.log_msg("按住{{x,y}} 参数错误({})\n".format(action), CLogger.MsgType.ERROR)
                        elif act == "key":
                            if "value" in keys:
                                key_value = int(action["value"])
                                key_value = AdbInterface.KeyCode(key_value)
                                self.log_msg("按键 {}\n".format(key_value.name))
                                self.adb.press_key(AdbInterface.KeyCode(key_value))
                            elif "name" in keys:
                                key_name = str(action["name"]).upper()
                                key_value = AdbInterface.KeyCode.NONE
                                for k in AdbInterface.KeyCode.__members__.items():
                                    if k[0] == key_name:
                                        key_value = k[1]
                                        break
                                if key_value is not AdbInterface.KeyCode.NONE:
                                    self.log_msg("按键 {}\n".format(key_value.name))
                                    self.adb.press_key(key_value)
                            else:
                                self.log_msg("按键{{name|value}} 参数错误({})\n".format(action), CLogger.MsgType.ERROR)
                        elif act == "text":
                            if "value" in keys:
                                text_value = action["value"]
                                self.log_msg("输入 {}\n".format(text_value))
                                self.adb.input_text(text_value)
                            else:
                                self.log_msg("输入{{value}} 参数错误({})\n".format(action), CLogger.MsgType.ERROR)
                        elif act == "msg":
                            msg_value = time.strftime("%Y-%m-%d %H:%M:%S ", time.localtime(time.time()))
                            if "value" in keys:
                                msg_value += action["value"]
                            self.log_msg("消息 {}\n".format(msg_value))
                        elif act == "cap":
                            if "name" in action:
                                cap_name = action["name"]
                                file_time = time.strftime("%Y%m%d%H%M%S", time.localtime(time.time()))
                                file_sn, _ = self.adb.get_device()
                                file_name = "screen/" + file_sn + "-" + file_time + "-" + cap_name + ".png"
                                if not os.path.exists("screen"):
                                    os.mkdir("screen")
                                succ, msg = self.adb.capture_screen(file_name)
                                if succ:
                                    self.log_msg("截屏 {}\n".format(cap_name))
                                else:
                                    self.log_msg("截屏失败({}) {}\n".format(msg, action), CLogger.MsgType.ERROR)
                            else:
                                self.log_msg("截屏{{name}} 参数错误({})\n".format(action), CLogger.MsgType.ERROR)
                        elif act == "call":
                            if "file" in action:
                                file_name = os.path.join(self.dir, action["file"])
                                progress_val = 0
                                if self.progress is not None:
                                    progress_val = self.progress.get_value()
                                self.log_msg("++++++++++++++++++++++++++++++++++++++++++++++++++\n")
                                self.log_msg("调用文件 {}\n".format(file_name))
                                self.log_msg("--------------------------------------------------\n")
                                CustomScriptThread(self.adb, file=file_name, parent=self).run()
                                self.log_msg("++++++++++++++++++++++++++++++++++++++++++++++++++\n")
                                if self.progress is not None:
                                    self.progress.set_value(progress_val)
                            else:
                                self.log_msg("调用{{file}} 参数错误({})\n".format(action), CLogger.MsgType.ERROR)
                        elif act == "nop":
                            self.log_msg("等待 {}s\n".format(act_time))
                            self.sleep(act_time)
                        else:
                            self.log_msg("未识别的指令: {}\n".format(act), CLogger.MsgType.ERROR)
                            self.sleep(act_time)
                        self._flag_continue.wait()
                        if not self._flag_run.is_set():
                            break
                        self.update_progress(i / action_count)
                    except Exception as ex:
                        self.log_msg(str(ex), CLogger.MsgType.ERROR)
                loop_count += 1
                self.reset_progress()
                if not self.loop_infinite and loop_count >= self.loop_times:
                    break
            if not self._flag_run.is_set():
                self.log_msg("\n用户停止！\n", CLogger.MsgType.INFO)
        except KeyboardInterrupt:
            try:
                self.log_msg("\n用户中止！\n", CLogger.MsgType.INFO)
            except Exception:
                pass
        except Exception as e:
            try:
                self.log_msg("\n发生错误：" + str(e) + "\n", CLogger.MsgType.ERROR)
            except Exception:
                pass
        tm_used = time.time() - tm_start
        tm_used /= 60
        try:
            self.log_msg("\n本次报告：总用时 {:.2f}分钟，执行 {}次。\n".format(tm_used, loop_count), CLogger.MsgType.INFO)
        except Exception:
            pass
        self._flag_stopped.set()


if __name__ == "__main__":
    print("非入口")
    exit(0)
